package cn.imvc.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.springframework.util.StringUtils;

public class ToolUtils {

	public static final String codes = "defhjkuvw23456789ABCDEFGHJKMNPQRSUVWXYZ";
	public static final String numbers = "0123456789";

	public static final String strs[] = { "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" };

	/**
	 * 生成随机码
	 * 
	 * @param length表示生成字符串的长度
	 * @return
	 */
	public static String getRandomString(int length) {
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(codes.length());
			sb.append(codes.charAt(number));
		}
		return sb.toString();
	}
	
	public static String getIpAddress(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_CLIENT_IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("HTTP_X_FORWARDED_FOR");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
	
	public static int getLeftMillis(){
		Calendar c = Calendar.getInstance();
		long now = c.getTimeInMillis();

		c.add(Calendar.DAY_OF_MONTH, 1);
		c.set(Calendar.HOUR_OF_DAY, 0);
		c.set(Calendar.MINUTE, 0);
		c.set(Calendar.SECOND, 0);
		c.set(Calendar.MILLISECOND, 0);

		return (int)((c.getTimeInMillis() - now)/1000);
	}
	
	public static String millisToDay(int millis){
		StringBuilder sb = new StringBuilder();
		int day = millis / (24 * 60 * 60);
		if (day > 0) {
			sb.append(day + "天");
		}
		millis = millis % (24 * 60 * 60);
		int hours = millis / (60 * 60);
		if(sb.indexOf("天") > 0){
			sb.append(hours + "小时");
		} else if (hours > 0) {
			sb.append(hours + "小时");
		}
		millis = millis % (60 * 60);
		int minutes = millis / 60;
		if(sb.indexOf("小时") > 0){
			sb.append(minutes + "分");
		} else if (minutes > 0) {
			sb.append(minutes + "分");
		}if(sb.indexOf("分") > 0){
			sb.append(millis % 60 + "秒");
		} else {
			sb.append(millis % 60 + "秒");
		}
		return sb.toString();
	}
	
	/**
	 * 生成随机数字
	 * 
	 * @param length表示生成数字字符串的长度
	 * @return
	 */
	public static String getRandomNumber(int length) {
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(numbers.length());
			sb.append(numbers.charAt(number));
		}
		return sb.toString();
	}

	/**
	 * 手机号验证
	 * 
	 * @param str
	 * @return 验证通过返回true
	 */
	public static boolean isMobile(String str) {
		Pattern p = null;
		Matcher m = null;
		boolean b = false;
		p = Pattern.compile("^1[3|4|5|7|8][0-9]\\d{8}$"); // 验证手机号
		m = p.matcher(str);
		b = m.matches();
		return b;
	}

	/**
	 * 邮箱验证
	 * 
	 * @param str
	 * @return 验证通过返回true
	 */
	public static boolean isEmail(String str) {
		Pattern p = null;
		Matcher m = null;
		boolean b = false;
		p = Pattern.compile("^([a-zA-Z0-9_\\.-])+@(([a-zA-Z0-9-])+\\.)+([a-zA-Z0-9]{2,4})+$");
		m = p.matcher(str);
		b = m.matches();
		return b;
	}

	public static void main(String[] args) {
		System.out.println(ToolUtils.millisToDay(3606));
	}

	/**
	 * 注册密码验证
	 * 
	 * @param str
	 * @return 验证通过返回true
	 */
	public static boolean isRegPasswd(String str) {
		Pattern p = null;
		Matcher m = null;
		boolean b = false;
		p = Pattern.compile("^\\w{6,18}$"); // 验证注册密码
		m = p.matcher(str);
		b = m.matches();
		return b;
	}

	/**
	 * 如果o为null则返回rvalue
	 * 
	 * @param o
	 * @param rvalue
	 * @return
	 */
	public static String toNvl(Object o, String rvalue) {
		if (StringUtils.isEmpty(o)) {
			return rvalue;
		} else if ("null".equalsIgnoreCase(String.valueOf(o))) {
			return rvalue;
		}
		return String.valueOf(o);
	}

	/**
	 * 是否为空， 为空返回 null； 不为空 type =1 去前后空格 type =2 去空格并转换大写 type = 3 去空格并转换小写
	 * 
	 * @return
	 */
	public static String stringTrimUpper(Object o, int type) {
		String string = "";
		try {
			if (StringUtils.isEmpty(o)) {
				return null;
			}

			if (!StringUtils.isEmpty(o) && type == 1) {
				return (String.valueOf(o)).trim();
			}

			if (!StringUtils.isEmpty(o) && type == 2) {
				return (String.valueOf(o)).trim().toUpperCase();
			}

			if (!StringUtils.isEmpty(o) && type == 3) {
				return (String.valueOf(o).trim().toLowerCase());
			}

		} catch (Exception ex) {

		}

		return string;
	}

	/**
	 * 判断是否为数字格式不限制位数
	 * 
	 * @param o
	 * @return
	 */
	public static boolean isNumber(Object o) {
		return (Pattern.compile("^[0-9]*$")).matcher(String.valueOf(o)).matches();
	}

	/**
	 * 判断是否为浮点数，包括double和float
	 * 
	 * @param str
	 *            传入的字符串
	 * @return 是浮点数返回true,否则返回false
	 */
	public static boolean isDouble(String str) {
		Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");

		boolean result = pattern.matcher(str).matches();
		if (result) {
			int count = 0;
			for (int i = 0; i < str.length(); i++) {
				if (".".equals(str.charAt(i)) || '.' == str.charAt(i))
					count++;
			}
			if (count > 1) {
				result = false;
			}
		}

		return result;
	}

	/**
	 * 判断是否为浮点数，包括double和float
	 * 
	 * @param str
	 *            传入的字符串
	 * @param length
	 *            小数点后位数
	 * @return 是浮点数返回true,否则返回false
	 */
	public static boolean isDouble(String str, int length) {
		String reg = "[+-]?[0-9]*.[0-9]{0," + length + "}";
		Pattern pattern = Pattern.compile(reg);

		boolean result = pattern.matcher(str).matches();
		if (result) {
			int count = 0;
			for (int i = 0; i < str.length(); i++) {
				if (".".equals(str.charAt(i)) || '.' == str.charAt(i))
					count++;
			}
			if (count > 1) {
				result = false;
			}
		}

		return result;
	}

	/**
	 * Long类型转换
	 * 
	 * @param str
	 * @return
	 */
	public static Double toDouble(String str) {
		Double i = null;
		try {
			if (null != str && !"".equals(str)) {
				i = new Double(str);
			}
		} catch (Exception ex) {
		}
		return i;
	}

	/**
	 * Long类型转换
	 * 
	 * @param str
	 * @return
	 */
	public static Long toLong(String str) {
		Long i = null;
		try {
			if (null != str && !"".equals(str)) {
				i = new Long(str);
			}
		} catch (Exception ex) {
		}
		return i;
	}

	/**
	 * BigDecimal类型转换
	 * 
	 * @param str
	 * @return
	 */
	public static BigDecimal toBigDecimal(String str) {
		BigDecimal bd = null;
		try {
			if (null != str && !"".equals(str)) {
				bd = new BigDecimal(str);
			}
		} catch (Exception ex) {
		}
		return bd;
	}

	/**
	 * Short类型转换
	 * 
	 * @param str
	 * @return
	 */
	public static Short toShort(String str) {
		Short st = null;
		try {
			if (null != str && !"".equals(str)) {
				st = new Short(str);
			}
		} catch (Exception ex) {
		}
		return st;
	}

	/**
	 * Integer类型转换
	 * 
	 * @param str
	 * @return
	 */
	public static Integer toInteger(String str) {

		Integer i = null;
		try {
			if (null != str && !"".equals(str)) {
				i = new Integer(str);
			}
		} catch (Exception ex) {
		}
		return i;
	}

	/**
	 * 字符串类型转换为整形
	 * 
	 * @param str
	 * @return
	 */
	public static int toInt(String str) {

		int i = 0;
		try {
			if (null != str && !"".equals(str)) {
				i = new Integer(str).intValue();
			}
		} catch (Exception ex) {
		}
		return i;
	}

	/**
	 * Date类型转换 字符串转换为java.util.Date 支持格式为 yyyy.MM.dd G 'at' hh:mm:ss z 如
	 * '2002-1-1 AD at 22:10:59 PSD' yy/MM/dd HH:mm:ss 如 '2002/1/1 17:55:00'
	 * yy/MM/dd HH:mm:ss pm 如 '2002/1/1 17:55:00 pm' yy-MM-dd HH:mm:ss 如
	 * '2002-1-1 17:55:00' yy-MM-dd HH:mm:ss am 如 '2002-1-1 17:55:00 am'
	 * 
	 * @param time
	 *            String 字符串
	 * @return Date 日期
	 */
	public static Date toDate(String time) {
		try {
			SimpleDateFormat formatter;

			if (time.indexOf("-") > -1) {// 包含“-”
				if (time.indexOf(":") == -1) {
					formatter = new SimpleDateFormat("yyyy-M-d");
				} else if (time.indexOf(":") == time.lastIndexOf(":")) {
					formatter = new SimpleDateFormat("yyyy-M-d HH:mm");
				} else {
					formatter = new SimpleDateFormat("yyyy-M-d HH:mm:ss");
				}
			} else if (time.indexOf("/") > -1) {// 包含“-”
				if (time.indexOf(":") == -1) {
					formatter = new SimpleDateFormat("yyyy/M/d");
				} else if (time.indexOf(":") == time.lastIndexOf(":")) {
					formatter = new SimpleDateFormat("yyyy/M/d HH:mm");
				} else {
					formatter = new SimpleDateFormat("yyyy/M/d HH:mm:ss");
				}
			} else if (time.indexOf(".") > -1) {// 包含“/”
				if (time.indexOf(":") == -1) {
					formatter = new SimpleDateFormat("yyyy.M.d");
				} else if (time.indexOf(":") == time.lastIndexOf(":")) {
					formatter = new SimpleDateFormat("yyyy.M.d HH:mm");
				} else {
					formatter = new SimpleDateFormat("yyyy.M.d HH:mm:ss");
				}
			} else if (time.length() == 14) {
				formatter = new SimpleDateFormat("yyyyMMddHHmmss");
			} else if (time.length() == 8) {
				formatter = new SimpleDateFormat("yyyyMMdd");
			} else {
				formatter = new SimpleDateFormat("HH:mm");
			}

			ParsePosition pos = new ParsePosition(0);
			java.util.Date ctime = formatter.parse(time, pos);

			return ctime;
		} catch (Exception e) {

		}
		return null;
	}

	public static String toString(String[] str) {
		return toString(str, ",");
	}

	public static String toString(String[] str, String delimiter) {
		// 此值传过来的为复选框，所以保存时用","号分隔
		String newStr = "";
		if (null != str) {
			for (int i = 1; i < str.length; i++) {
				newStr = newStr + delimiter + str[i];
			}
		}
		return newStr;
	}

	/**
	 * 四舍五入 number为四舍五入的数字
	 * <p/>
	 * keta是保留小数点之后的位数，从0开始 （0，1，2，3，其他）
	 * <p/>
	 * 0: 表示整数 （155.5->156） 1:(0.05->0.10) 2:(0.05 ->0.10) 3：(0.005-0.010)
	 * 其他:(0.00005-0.0001)
	 */
	public static Double rounds(Double number, int keta) {
		String fmt = "";
		switch (keta) {
		case 0:
			fmt = "#0";
			break;
		case 1:
			fmt = "#0.0";
			break;
		case 2:
			fmt = "#0.00";
			break;
		case 3:
			fmt = "#0.000";
			break;
		default:
			fmt = "#0.0000";
			break;
		}
		DecimalFormat df = new DecimalFormat(fmt);
		return Double.valueOf(df.format(number));
	}

	/**
	 * 左侧补位
	 * 
	 * @param value
	 *            原值
	 * @param length
	 *            长度
	 * @param padValue
	 *            填补值
	 * @return
	 */
	public static String leftPad(String value, int length, String padValue) {
		for (int i = value.length(); i < length; i++) {
			value = padValue + value;
		}
		return value;
	}

	/**
	 * 右侧补位
	 * 
	 * @param value
	 *            原值
	 * @param length
	 *            长度
	 * @param padValue
	 *            填补值
	 * @return
	 */
	public static String rightPad(String value, int length, String padValue) {
		for (int i = value.length(); i < length; i++) {
			value += padValue;
		}
		return value;
	}

	/**
	 * 对date 加天数得到新日期
	 * 
	 * @param date
	 * @param days
	 * @return
	 */
	public static Date addDate(Date date, int days) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, days);// 日期加days指定天数
		return calendar.getTime();
	}

	/**
	 * 根据当前月份加月份获取新日期
	 * 
	 * @param date
	 * @param month
	 * @return
	 */
	public static Date addMonth(Date date, int month) {
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		c.add(Calendar.MONTH, month);
		return c.getTime();
	}

	public static int getCurYear() {
		Calendar calendar = Calendar.getInstance();
		return calendar.get(Calendar.YEAR);
	}

	public static int getDateYear(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}

	public static int getDateYear(String time) {
		Date date = ToolUtils.toDate(time);
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		return calendar.get(Calendar.YEAR);
	}

	public static int getMinute(Date date) {
		Calendar calendar = Calendar.getInstance();
	    calendar.setTime(date);
	    return calendar.get(Calendar.MINUTE);
	}

	public static String getDateFormat(Date date, String format) {
		if (StringUtils.isEmpty(date))
			return null;
		SimpleDateFormat df = new SimpleDateFormat(format);// 设置日期格式
		return df.format(date);
	}

	public static String getDateFormat(String date, String format) {
		SimpleDateFormat df = new SimpleDateFormat(format);// 设置日期格式
		return df.format(toDate(date));
	}

	/**
	 * 校验日期格式 yyyyMMddHHmmss
	 * 
	 * @param checkDate
	 * @return
	 */
	public static boolean checkDateFormat(String checkDate) {
		boolean flag = false;

		if (StringUtils.isEmpty(checkDate)) {
			return flag;
		}

		if (checkDate.length() != 14 && checkDate.length() != 12 && checkDate.length() != 8) {
			return flag;
		}

		String year = checkDate.substring(0, 4); // 获取年份
		String month = checkDate.substring(4, 6); // 获取月份
		Boolean isLeap = ToolUtils.isLeapYear(Integer.parseInt(year)); // 判断闰年
		StringBuffer eL = new StringBuffer();
		String longMonth = "01030507081012"; // 31天的月份
		String fix = "([2][0-3]|[0-1][0-9]|[1-9])[0-5][0-9]([0-5][0-9]|[6][0])";

		if (checkDate.length() == 8) {// yyyyMMdd
			if (isLeap && month.equals("02")) { // 针对2月份的情况 【闰年】
				eL.append("\\d{4}([1][0-2]|[0][0-9])([1-2][0-9]|[0][1-9]|[1-9])");
			} else if (!isLeap && month.equals("02")) { // 针对2月份的情况 【非闰年】
				eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-8]|[1][0-9]|[0][1-9]|[1-9])");
			} else if (longMonth.contains(month)) { // 31天月份
				eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0-1]|[1-2][0-9]|[0][1-9]|[1-9])");
			} else { // 30天月份
				eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0]|[1-2][0-9]|[0][1-9]|[1-9])");
			}
		}

		if (checkDate.length() == 12) {// yyyyMMddHHmm
			fix = "([2][0-3]|[0-1][0-9]|[1-9])[0-5][0-9]";

			if (isLeap && month.equals("02")) { // 针对2月份的情况 【闰年】
				eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-1]|[1-2][0-9]|[0][1-9]|[1-9])" + fix);
			} else if (!isLeap && month.equals("02")) { // 针对2月份的情况 【非闰年】
				eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-8]|[1][0-9]|[0][1-9]|[1-9])" + fix);
			} else if (longMonth.contains(month)) { // 31天月份
				eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0-1]|[1-2][0-9]|[0][1-9]|[1-9])" + fix);
			} else { // 30天月份
				eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0]|[1-2][0-9]|[0][1-9]|[1-9])" + fix);
			}
		}

		if (checkDate.length() == 14) {// yyyyMMddHHmmss
			if (isLeap && month.equals("02")) { // 针对2月份的情况 【闰年】
				eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-1]|[1-2][0-9]|[0][1-9]|[1-9])" + fix);
			} else if (!isLeap && month.equals("02")) { // 针对2月份的情况 【非闰年】
				eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-8]|[1][0-9]|[0][1-9]|[1-9])" + fix);
			} else if (longMonth.contains(month)) { // 31天月份
				eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0-1]|[1-2][0-9]|[0][1-9]|[1-9])" + fix);
			} else { // 30天月份
				eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0]|[1-2][0-9]|[0][1-9]|[1-9])" + fix);
			}
		}

		Pattern p = Pattern.compile(eL.toString());
		Matcher m = p.matcher(checkDate);
		flag = m.matches();
		return flag;
	}

	/**
	 * 判断是否为闰年
	 * 
	 * @param year
	 * @return
	 */
	public static boolean isLeapYear(int year) {
		Boolean isLeap = false;
		if (((year % 100 == 0) && (year % 400 == 0)) || ((year % 100 != 0) && (year % 4 == 0))) {
			isLeap = true;
		}
		return isLeap;
	}

	/**
	 * 获得汉字的长度
	 * 
	 * @param s
	 * @return
	 * @throws Exception
	 */
	public static int getChineseCount(String s) {
		char c;
		int chineseCount = 0;
		try {
			if (!"".equals("")) {// 判断是否为空
				s = new String(s.getBytes(), "GBK"); // 进行统一编码
			}
			for (int i = 0; i < s.length(); i++) {// for循环
				c = s.charAt(i); // 获得字符串中的每个字符
				if (String.valueOf(c).getBytes("GBK").length > 1) {// 调用方法进行判断是否是汉字
					chineseCount++; // 等同于chineseCount=chineseCount+1
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
		return chineseCount; // 返回汉字个数
	}

	/**
	 * 校验字符串长度
	 * 
	 * @param str
	 * @param lenght
	 * @return
	 */
	public static int getStringLength(String str) {
		if (StringUtils.isEmpty(str)) {
			return 0;
		}
		return str.length() + ToolUtils.getChineseCount(str);
	}

	/**
	 * 
	 * @param 要转换的毫秒数
	 * @return 该毫秒数转换为 * days * hours * minutes * seconds 后的格式
	 * @author liujunli
	 */
	public static String formatDuring(long mss) {
		long days = mss / (1000 * 60 * 60 * 24);
		long hours = (mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
		long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
		long seconds = (mss % (1000 * 60)) / 1000;

		StringBuffer str = new StringBuffer();
		if (days != 0) {
			str.append(days + "天");
		}
		if (hours != 0) {
			str.append(hours + "小时");
		}
		if (minutes != 0) {
			str.append(minutes + "分钟");
		}
		if (seconds != 0) {
			str.append(seconds + "秒");
		}

		return str.toString();
	}

	/**
	 * 
	 * @param begin
	 *            时间段的开始
	 * @param end
	 *            时间段的结束
	 * @return 输入的两个Date类型数据之间的时间间格用* days * hours * minutes * seconds的格式展示
	 * @author liujunli
	 */
	public static String formatDuring(Date begin, Date end) {
		return formatDuring(end.getTime() - begin.getTime());
	}

	/**
	 * @功能描述：获取uuid
	 * @author: liujunli
	 * @date:2016年7月16日10:21:16
	 * @return
	 */
	public static String getUUID() {
		String uuid = UUID.randomUUID().toString();
		uuid = uuid.replaceAll("-", "").toUpperCase();
		return uuid;
	}
	/**
	 * 获取中文带星期的日期
	 * @return
	 */
	public static String getFormatedCNdateWithWeek(){
		Calendar c = Calendar.getInstance();
		int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
		String CNdayOfweek = "";
		switch (dayOfWeek) {
		case 1:
			CNdayOfweek = "星期日";
			break;
		case 2:
			CNdayOfweek = "星期一";

			break;
		case 3:
			CNdayOfweek = "星期二";

			break;
		case 4:
			CNdayOfweek = "星期三";

			break;
		case 5:
			CNdayOfweek = "星期四";

			break;
		case 6:
			CNdayOfweek = "星期五";
			break;
		case 7:
			CNdayOfweek = "星期六";
			break;
		default:
			break;
		}
		SimpleDateFormat sf = new SimpleDateFormat("yyyy年M月d日");
		String dataFormted = sf.format(c.getTime()) + " " + CNdayOfweek;
		return dataFormted;
	}
}
